#include <includes.h>
#include <lpc17xx.h>
#include "lpc17xx_adc.h"
#include "lpc17xx_libcfg.h"
#include "lpc17xx_pinsel.h"
#include "debug_frmwrk.h"
#include "lpc17xx_gpio.h"
#include "lpc17xx_gpdma.h"
#include <LCD_task.h>
#include <SSD1298_driver.h>
#include "temperature.h"

uint32_t adc_value;
uint32_t Channel0_TC;
uint32_t Channel0_Err;
uint8_t  ADC_Channel;
uint8_t  ADC_Done;
uint8_t  AddCnt;
static uint32_t Resault;
static uint32_t ResAdd;


volatile uint16_t TempCnt;
volatile uint16_t TempTickCnt;

void i32toc(uint32_t Num,uint8_t *Des)
{
	uint8_t DesNum;
	
	*(Des++) = ((uint8_t)(Num >> 28 )) & 0x0F;
	*(Des++) = ((uint8_t)(Num >> 24 )) & 0x0F;
	*(Des++) = ((uint8_t)(Num >> 20 )) & 0x0F;
	*(Des++) = ((uint8_t)(Num >> 16 )) & 0x0F;
	*(Des++) = ((uint8_t)(Num >> 12 )) & 0x0F;
	*(Des++) = ((uint8_t)(Num >> 8  )) & 0x0F;
	*(Des++) = ((uint8_t)(Num >> 4  )) & 0x0F;
	*(Des++) = ((uint8_t)(Num)) & 0x0F       ;
	
	Des -= 8;
	
	DesNum = 8;
	
	while(DesNum--)
	{
		if(*Des < 10)
            *Des  +=  0x30;
        else
            *Des  +=  ('A' - 10);
		
		Des ++;
	}
	
}

/*----------------- INTERRUPT SERVICE ROUTINES --------------------------*/
/*********************************************************************//**
 * @brief		ADC interrupt handler sub-routine
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void ADC_IRQHandler(void)
{
	uint32_t ADC_Data;
	uint32_t ADC_Rec_Channel;
	adc_value = 0;
	ADC_Data  = LPC_ADC->ADGDR  ;
	ADC_Rec_Channel = (ADC_Data >> 24) & 0x07 ;
	
	switch(ADC_Rec_Channel)
	{
		case 0 :
			adc_value = LPC_ADC->ADDR0 & (0x0FFF << 4) ; break;
		case 1 :
			adc_value = LPC_ADC->ADDR1 & (0x0FFF << 4) ; break;
		case 2 :
			adc_value = LPC_ADC->ADDR2 & (0x0FFF << 4) ; break;
		case 3 :
			adc_value = LPC_ADC->ADDR3 & (0x0FFF << 4) ; break;
		case 4 :
			adc_value = LPC_ADC->ADDR4 & (0x0FFF << 4) ; break;
		case 5 :
			adc_value = LPC_ADC->ADDR5 & (0x0FFF << 4) ; break;
		case 6 :
			adc_value = LPC_ADC->ADDR6 & (0x0FFF << 4) ; break;
		case 7 :
			adc_value = LPC_ADC->ADDR7 & (0x0FFF << 4) ; break;
		default :
			break;
	}
	
	if( (AddCnt++) < 64)
		ResAdd += ( adc_value >>= 4 );
	else
	{
		Resault = ResAdd >> 6;
		ResAdd  = 0;
		AddCnt  = 0;
	}
	
	LPC_ADC->ADCR &= ~ADC_CR_START_MASK;
	LPC_ADC->ADCR |= ADC_CR_START_NOW;
}

/*********************************************************************//**
 * @brief		GPDMA interrupt handler sub-routine
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void DMA_IRQHandler (void)
{
	// check GPDMA interrupt on channel 0
	if (GPDMA_IntGetStatus(GPDMA_STAT_INT, 0))
	{
		// Check counter terminal status
		if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0))
		{
			// Clear terminate counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);

			Channel0_TC++;
		}

		// Check error terminal status
		if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0))
		{
			// Clear error counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);

			Channel0_Err++;
		}
	}
}


void ADC_Task(void * p_arg)
{
    PINSEL_CFG_Type PinCfg;

	OS_ERR err;
	p_arg = p_arg;
	
	/*
	 * Init ADC pin connect
	 * AD0.5 on P1.31
	 */
	PinCfg.Funcnum = 3;
	PinCfg.OpenDrain = 0;
	PinCfg.Pinmode = 0;
	PinCfg.Pinnum = 31;
	PinCfg.Portnum = 1;
	PINSEL_ConfigPin(&PinCfg);
	
	ADC_Init(LPC_ADC, 10000);
	ADC_ChannelCmd(LPC_ADC,ADC_CHANNEL_5,ENABLE);
	
	ADC_Channel=5;
	
	//  Int Config
    LPC_ADC->ADINTEN |= _BIT(ADC_Channel);      //enable int 
	LPC_ADC->ADINTEN |= _BIT(8);                //enable global int 

	
    NVIC_SetPriority(ADC_IRQn, ((0x01<<3)|0x01));
    NVIC_EnableIRQ(ADC_IRQn);
	
	TempInit();
	TempMarkTable[0].MarkADL = 4000;
    TempMarkTable[0].MarkADH = 30000;
    TempCorrectTable[0].PB   = 0;
    TempCorrectTable[0].PK   = 0;
    TempLimiteTable[0].LimiteL = -200;
    TempLimiteTable[0].LimiteH = 1500;
	TempTickCnt = 0;
	TempCnt = 0;
	
	/*
	// DMA MODE
	  GPDMA_Init();
	// Setup GPDMA channel --------------------------------
	// channel 0
	  GPDMACfg.ChannelNum = 0;
	// Source memory - unused
	  GPDMACfg.SrcMemAddr = 0;
	// Destination memory
	  GPDMACfg.DstMemAddr = (uint32_t)s_buf;
	// Transfer size
	  GPDMACfg.TransferSize = DMA_SIZE;
	// Transfer width - unused
	  GPDMACfg.TransferWidth = 0;
	// Transfer type
	  GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_P2M;
	// Source connection
	  GPDMACfg.SrcConn = GPDMA_CONN_ADC;
	// Destination connection - unused
	  GPDMACfg.DstConn = 0;
	// Linker List Item - unused
	  GPDMACfg.DMALLI = 0;
	// Enable GPDMA interrupt 
	  NVIC_EnableIRQ(DMA_IRQn);
	*/
	
	LCD_String_ADC.Data[0]  = 'A' ;
	LCD_String_ADC.Data[1]  = 'D' ;
	LCD_String_ADC.Data[2]  = 'C' ;
	LCD_String_ADC.Data[3]  = '_' ;
	LCD_String_ADC.Data[4]  = 'D' ;
	LCD_String_ADC.Data[5]  = 'A' ;
	LCD_String_ADC.Data[6]  = 'T' ;
	LCD_String_ADC.Data[7]  = 'A' ;
	LCD_String_ADC.Data[8]  = ' ' ;
    LCD_String_ADC.Data[8]  = '\0' ;
	
	LCD_String_ADC.StartX   = 6*8;
	LCD_String_ADC.StartY   = 2*16;
	LCD_String_ADC.BackColor  = Blue;
	LCD_String_ADC.PointColor = White;
	LCD_String_ADC.OnOff      = DISPLAY_ON ;
	
	LPC_ADC->ADCR &= ~(7<<24) ;
	LPC_ADC->ADCR |= 1<<24 ;
	
	ADC_Done = 0;
	ResAdd   = 0;
	AddCnt   = 0;
	while(1)
    {   
		OSTimeDly(1000,OS_OPT_TIME_DLY,&err);

		TempTickCnt = 0;
		TempCnt = 0;
		
		while( TempTickCnt < 100 )
		{
			TempADSet(0 ,9652);
			TempCal(0);
			TempCnt++;
		}
		TempCnt = TempCnt;
		
		
		if(LCD_String_ADC.OnOff == 0)                // 
		{
			i32toc(Resault,LCD_String_ADC.Data);
			LCD_String_ADC.StartX   = 16*8;
			LCD_String_ADC.OnOff    = DISPLAY_ON;
		}
		
/*		
        for(tmp = 0; tmp < 0x1000; tmp++);

        // Reset terminal counter 
	    Channel0_TC = 0;
	    // Reset Error counter 
	    Channel0_Err = 0;
        for(tmp = 0; tmp < DMA_SIZE; tmp++)
        {
            s_buf[tmp] = 0;
        }
        //Start burst conversion
        ADC_BurstCmd(LPC_ADC,ENABLE);

        GPDMA_Setup(&GPDMACfg);
        // Enable GPDMA channel 0
        GPDMA_ChannelCmd(0, ENABLE);
        // Wait for GPDMA processing complete
      	while ((Channel0_TC == 0));
        GPDMA_ChannelCmd(0, DISABLE);
        
         for(tmp = 0; tmp < DMA_SIZE; tmp++)
         {
		  
         }
*/					
    }


/*
	//Start burst conve
	  LPC_ADC->ADCR &= (~ADC_CR_START_MASK);      //clear bits : Start
	  LPC_ADC->ADCR |= ADC_CR_START_MODE_SEL(0);  //set adc mode
	  ADCx->ADCR &= ~ADC_CR_BURST;                //clear bit : burst 
	  ADCx->ADCR |= ADC_CR_BURST;                 //enable burst mode
*/

/*  Start CAP/MAT
    ADCx->ADCR &= ~ADC_CR_EDGE;                 //Start at up CAP/MAT
	ADCx->ADCR |=  ADC_CR_EDGE;                 //Start at down CAP/MAT 
*/

/*  Channel Select
    ADCx->ADCR |= ADC_CR_CH_SEL(Channel);       //slect channel 
	
	  ADCx->ADCR &= ~ADC_CR_START_MASK;           //need to stop START bits before disable channel if disable channel
  	ADCx->ADCR &= ~ADC_CR_CH_SEL(Channel);      //disable channel
*/

/*  Int Config
    LPC_ADC->ADINTEN |= _BIT(channel);          //enable int 
  	LPC_ADC->ADINTEN &= ~(_BIT(channel));       //disable int
	LPC_ADC->ADINTEN |= _BIT(8);                //enable global int 
	LPC_ADC->ADINTEN &= ~(_BIT(8));             //disable global int
	
    NVIC_SetPriority(ADC_IRQn, ((0x01<<3)|0x01));
    NVIC_EnableIRQ(ADC_IRQn);
*/

/*  Data Read
    if(LPC_ADC->ADSTAT & (1u << channel))        //If done ,read data
    {
	      adc_value = (*(uint32_t *) ((&ADCx->ADDR0) + channel)) & ((~3) << 30);
	  }
*/


/*  Data Read
	  ADCSTAT_TEMP    = LPC_ADC->ADSTAT;
	  LPC_ADC->ADSTAT = 0;
    if(ADCSTAT_TEMP & (1u << 16))                //Int flag
    {
	      if(ADCSTAT_TEMP & (1u)                   //If done ,read data
        {
	          adc_value = &ADCx->ADDR0 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 1))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR1 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 2))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR2 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 3))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR3 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 4))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR4 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 5))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR5 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 6))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR6 & ((~3) << 30);
	      }
		    else if(ADCSTAT_TEMP & (1u << 7))        //If done ,read data
        {
	          adc_value = &ADCx->ADDR7 & ((~3) << 30);
	      }
	  }
*/

/*  Read Global Data
    GlobalData_temp = LPC_ADC->ADGDR;
*/

/*  Start Mode
    ADCx->ADCR &= ~ADC_CR_START_MASK;
	ADCx->ADCR |=ADC_CR_START_MODE_SEL((uint32_t)start_mode);
*/

}
